import { Injectable } from '@angular/core';
import { AbstractControl, FormControl } from '@angular/forms';
import { Subscription } from 'rxjs';
import * as CryptoJS from 'crypto-js';

@Injectable({
    providedIn: 'root'
})
export class ValidatorService {
    constructor() {
    }

    /**
     * 银行卡号验证
     * @param control 表单元素
     */
    bankCardNumberValidator(control: FormControl): any {
        const CARD_REGEXP = /^([1-9]{1})(\d{15}|\d{18})$/;
        if (control.value) {
            if (!CARD_REGEXP.test(control.value.toString().replace(/\s/g, ''))) {
                return {
                    error: true,
                    bankCardNumber: true
                };
            }
        }
    }

    /**
     * 是否为浮点数
     * @param control 表单元素
     */
    floatingPointValidator(control: FormControl): any {
        const FLOAT_REGEXP = /^(([1-9]\d{0,9})|0)(\.\d{1,2})?$/i;
        if (!control.value) {
            return { required: true };
        } else if (!FLOAT_REGEXP.test(control.value.toString().replace(/\s/g, ''))) {
            return {
                error: true,
                floatingPoint: true
            };
        }
    }

    /**
     * 手机号验证
     * @param control 表单元素
     */
    mobileValidator(control: FormControl): any {
        const MOBILE_REGEXP = /^[1][3456789][0-9]{9}$/i;
        if (control.value) {
            if (!MOBILE_REGEXP.test(control.value.toString().replace(/\s/g, ''))) {
                return { error: true, mobile: true };
            }
        }
    }

    /**
     * 结束日期大于开始日期
     *  @param control 表单元素
     */
    compareDateValidator(control: FormControl): any {
        if (control.value) {
            if (control.value.length > 0) {
                if (control.value[0].toString() === control.value[1].toString()) {
                    return { error: true, compareDate: true };
                }
            }
        }
    }

    /**
     * 身份证号验证
     * @param control 表单元素
     */
    identityValidator(control: FormControl): any {
        const REGEXP = /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/i;
        if (control.value) {
            if (!REGEXP.test(control.value.toString().replace(/\s/g, ''))) {
                return { error: true, identity: true };
            }
        }
    }

    /**
     * 两次密码校验
     * @param targetField 目标表单元素
     */
    validateEqual(targetField: string): any {
        return (self: AbstractControl): { [key: string]: any } => {
            //这里严格按照ValidatorFn的声明来
            const _form = self.parent;
            if (_form) {
                const targetControl: AbstractControl = _form.controls[targetField];
                if (targetControl.value && self.value !== targetControl.value) {
                    //如果两个值不一致
                    return { error: true, match: true };
                }
            }
        };
    }

    /**
     * 只能输入英文
     * @param control 表单元素
     */
    englishValidator(control: FormControl): any {
        const REG = /^[5A-Za-z\_]+$/;
        if (control.value) {
            if (!REG.test(control.value.toString().replace(/\s/g, ''))) {
                return { error: true, english: true };
            }
        }
    }

    /**
     * 输入框空格校验
     * @param control 表单元素
     */
    blankValidator(control: FormControl): any {
        if (control.value) {
            if (control.value.indexOf(' ') !== -1) {
                return { error: true, blank: true };
            }
        }
    }

    /**
     * 密码校验
     * @param control 表单元素
     */
    passwordValidator(control: FormControl): any {
        const REG = /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,20}$/;
        if (control.value) {
            if (!REG.test(control.value.toString().replace(/\s/g, ''))) {
                return { error: true, password: true };
            }
        }
    }

    /**
     * 是否为整数检验
     * @param control 表单元素
     */
    isNumberValidator(control: FormControl): any {
        const REG = /^\+?(?!0)\d*$/;
        if (control.value) {
            if (!REG.test(control.value.toString().replace(/\s/g, ''))) {
                return { error: true, isNumber: true };
            }
        }
    }

    /**
     * 判断是否是连续的数字
     * @param control 表单元素
     */
    isContinuousNumber(control: FormControl): any {
        if (control.value !== null) {
            const val: any = control.value.sort();
            let continuousNumber = '';
            val.forEach((item) => {
                continuousNumber += item.toString();
            });
            if (continuousNumber.length > 1) {
                for (let i = 0, l = continuousNumber.length; i < l - 1; i++) {
                    if (continuousNumber.charCodeAt(i) - continuousNumber.charCodeAt(i + 1) !== -1) {
                        return { error: true, isContinuous: true };
                    }
                }
            }
        }
    }

    /**
     * 前后输入框数字大小限制
     * @param targetFiled 目标表单元素
     */
    compareNumber(targetFiled: string): any {
        return (self: AbstractControl): { [key: string]: any } => {
            const _form = self.parent;
            if (_form) {
                const targetControl: AbstractControl = _form.controls[targetFiled];
                const subscription: Subscription = targetControl.valueChanges.subscribe(() => {
                    self.updateValueAndValidity();
                    subscription.unsubscribe();
                });
                if (parseInt(targetControl.value, 0) > parseInt(self.value, 0)) {
                    return { error: true, match: true };
                }
            }
        };
    }

    /**
     * 前后输入框字符串大小
     * @param targetFiled 目标文本框输入值
     */
    compareString(targetFiled: string): any {
        return (self: AbstractControl): { [key: string]: any } => {
            const _form = self.parent;
            if (_form) {
                const targetControl: AbstractControl = _form.controls[targetFiled];
                const subscription: Subscription = targetControl.valueChanges.subscribe(() => {
                    self.updateValueAndValidity();
                    subscription.unsubscribe();
                });
                if (targetControl.value > self.value) {
                    return { error: true, compareString: true };
                }
            }
        };
    }

    /**
     * 短号验证
     * @param control 表单元素
     */
    numberValidator(control: FormControl): any {
        const MOBILE_REGEXP = /^[0-9a-zA-Z_]{1,}$/i;
        if (!control.value) {
            return { required: true };
        } else if (!MOBILE_REGEXP.test(control.value.toString().replace(/\s/g, ''))) {
            return { error: true, match: true };
        }
    }

    /**
     * 正整数验证
     * @param control 表单元素
     */
    positiveIntegerValidator(control: FormControl): any {
        const REG = /^\+?(?!0)\d*$/;
        if (control.value) {
            if (!REG.test(control.value.toString().replace(/\s/g, ''))) {
                return { error: true, positiveInteger: true };
            }
        }
    }

    /**
     * 整数验证
     * @param control 表单元素 表单元素
     */
    integerValidator(control: FormControl): any {
        const REG = /^-?\d+$/;
        if (control.value) {
            if (!REG.test(control.value.toString().replace(/\s/g, ''))) {
                return { error: true, positiveIsInteger: true };
            }
        }
    }

    /**
     * 英文字符验证
     * @param control 表单元素
     */
    enstringValidator(control: FormControl): any {
        const EN_REGEXP = new RegExp('^[a-zA-Z]+$');
        if (!control.value) {
            return { required: true };
        } else if (!EN_REGEXP.test(control.value.toString().replace(/\s/g, ''))) {
            return { error: true, enString: true };
        }
    }

    /**
     * 数字和英文的编号字符验证
     * @param control 表单元素
     */
    isNumberingstringValidator(control: FormControl): any {
        const EN_REGEXP = new RegExp('^[0-9a-zA-Z]+$');
        if (!control.value) {
            return { required: true };
        } else if (!EN_REGEXP.test(control.value.toString().replace(/\s/g, ''))) {
            return { error: true, isNumbering: true };
        }
    }

    /**
     * 金额验证
     * @param control 表单元素
     */
    isMoneyValidator(control: FormControl): any {
        const REGEXP = new RegExp('^(([1-9][0-9]{0,14})|([0]{1})|(([0]\\.\\d{1,2}|[1-9][0-9]{0,14}\\.\\d{1,2})))$');
        if (control.value) {
            if (!REGEXP.test(control.value)) {
                return { error: true, isMoney: true };
            }
        }
    }

    /**
     * 邮箱地址验证
     * @param control 表单元素
     */
    emailValidator(control: FormControl): any {
        const REGEXP = new RegExp('^[a-z0-9A-Z]+[- | a-z0-9A-Z . _]+@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-z]{2,}$');
        if (control.value) {
            if (!REGEXP.test(control.value)) {
                return { error: true, email: true };
            }
        }
    }

    /**
     * 加密处理
     */
    encryption = (params) => {
        let {
            data,
            type,
            param,
            key
        } = params;
        const result = JSON.parse(JSON.stringify(data));
        if (type === 'Base64') {
            param.forEach(ele => {
                result[ele] = btoa(result[ele]);
            });
        } else {
            param.forEach(ele => {
                let data = result[ele];
                key = CryptoJS.enc.Latin1.parse(key);
                var iv = key;
                // 加密
                var encrypted = CryptoJS.AES.encrypt(
                    data,
                    key, {
                        iv: iv,
                        mode: CryptoJS.mode.CBC,
                        padding: CryptoJS.pad.ZeroPadding
                    });
                result[ele] = encrypted.toString();

            });
        }
        return result;
    };
}
